package com.guigusuqi.commonutils.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.guigusuqi.commonutils.exeception.AddressErrorException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

public class AddressLngLatExchangerUtils
{

    private static final String GOULD_KEY = "7996589be81b93ae690bee544a5943df";

    /**
     * 高德地图通过地址获取经纬度
     */
    public static Map<String, Double> addressToLngAndLag(String address)
    {
        Map<String, Double> map = new HashMap<String, Double>();
        //https://restapi.amap.com/v3/geocode/geo?address=上海市东方明珠&output=JSON&key=bc2bca34c9d3fccd2d10a1516ebae89e
        String geturl = "http://restapi.amap.com/v3/geocode/geo?key=" + GOULD_KEY + "&address=" + address;
        String location = "";
        try
        {
            URL url = new URL(geturl);    // 把字符串转换为URL请求地址
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 打开连接
            connection.connect();// 连接会话
            // 获取输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null)
            {// 循环读取流
                sb.append(line);
            }
            br.close();// 关闭流
            connection.disconnect();// 断开连接
            JSONObject a = JSON.parseObject(sb.toString());
            JSONArray sddressArr = JSON.parseArray(a.get("geocodes").toString());
            if (sddressArr.size() == 0)
            {
                throw new AddressErrorException(404,"地址无法找到");
            }
            JSONObject c = JSON.parseObject(sddressArr.get(0).toString());
            location = c.get("location").toString();
        } catch (Exception e)
        {
            e.printStackTrace();
            throw new AddressErrorException(404,"地址无法找到");
        }
        return stringToMap(location);
    }

    public static Map<String, Double> stringToMap(String LngLat)
    {
        Map<String, Double> map = new HashMap<String, Double>();
        String[] strArr = LngLat.split("\\,");
        map.put("lng", Double.parseDouble(strArr[0]));
        map.put("lat", Double.parseDouble(strArr[1]));
        return map;
    }

    /**
     * 0.根据地址名称得到两个地址间的距离
     *
     * @param start 起始位置
     * @param start 结束位置
     * @return 两个地址间的距离
     */
    public static long getDistanceByAddress(String start, String end)
    {
        String startLonLat = getLngLat(start);
        String endLonLat = getLngLat(end);
        long dis = getDistance(startLonLat, endLonLat);
        return dis;
    }

    /**
     * 1.地址转换为经纬度
     *
     * @param address 地址
     * @return 经纬度
     */
    public static String getLngLat(String address) {
        // 返回输入地址address的经纬度信息, 格式是 经度,纬度
        String queryUrl = "http://restapi.amap.com/v3/geocode/geo?key=" + GOULD_KEY + "&address=" + address;
        String queryResult = getResponse(queryUrl); // 高德接品返回的是JSON格式的字符串
        JSONObject job = JSONObject.parseObject(queryResult);
        JSONObject jobJSON = JSONObject
                .parseObject(job.get("geocodes").toString().substring(1, job.get("geocodes").toString().length() - 1));
        String DZ = jobJSON.get("location").toString();
//		System.out.println("经纬度：" + DZ);
        return DZ;
    }


    /**
     * 将经纬度getLng， getLat 通过getAMapByLngAndLat方法转换地址
     * @param getLng 经度
     * @param getLat 纬度
     * @return 地址名称
     * @throws Exception
     */
    public static String getAMapByLngAndLat(String getLng, String getLat)
    {
        String url;
        try {
            url = "http://restapi.amap.com/v3/geocode/regeo?output=JSON&location=" + getLng + "," + getLat
                    + "&key=" + GOULD_KEY + "&radius=0&extensions=base";
            System.out.println(getLat);
            System.out.println(url);
            String queryResult = getResponse(url); // 高德接品返回的是JSON格式的字符串
            if (queryResult == null) {
                return "-1";
            }
            // 将获取结果转为json 数据
//            .stringToValue(queryResult)
            JSONObject obj = JSONObject.parseObject(queryResult);
            if (obj.get("status").toString().equals("1")) {
                // 如果没有返回-1
                JSONObject regeocode = obj.getJSONObject("regeocode");
                if (regeocode.size() > 0) {
                    // 在regeocode中拿到 formatted_address 具体位置
                    String formatted = regeocode.get("formatted_address").toString();
                    return formatted;

                } else {
                    System.out.println("未找到相匹配的地址！");
                    return "-1";

                }
            } else {
                System.out.println("请求错误！");
                return "-1";
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "-1";
    }

    /**
     * 2.根据两个定位点的经纬度算出两点间的距离
     *
     * @param startLngLat 起始经纬度
     * @param endLngLat   结束经纬度（目标经纬度）
     * @return 两个定位点之间的距离
     */
    public static long getDistance(String startLngLat, String endLngLat) {
        // 返回起始地startAddr与目的地endAddr之间的距离，单位：米
        Long result = new Long(0);
        String queryUrl = "http://restapi.amap.com/v3/distance?key=" + GOULD_KEY + "&origins=" + startLngLat + "&destination="
                + endLngLat;
        String queryResult = getResponse(queryUrl);
        JSONObject job = JSONObject.parseObject(queryResult);
        JSONArray ja = job.getJSONArray("results");
        JSONObject jobO = JSONObject.parseObject(ja.getString(0));

        result = Long.parseLong(jobO.get("distance").toString());
//		System.out.println("距离2：" + result);
        return result;
    }

    /**
     * 3.发送请求
     *
     * @param serverUrl 请求地址
     */
    private static String getResponse(String serverUrl) {
        // 用JAVA发起http请求，并返回json格式的结果
        StringBuffer result = new StringBuffer();
        try {
            URL url = new URL(serverUrl);
            URLConnection conn = url.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            in.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result.toString();
    }

    /**
     * 地球半径,单位 m
     */
    private static final double EARTH_RADIUS = 6378137;

    /**
     * 根据经纬度，计算两点间的距离
     *
     * @param longitude1 第一个点的经度
     * @param latitude1  第一个点的纬度
     * @param longitude2 第二个点的经度
     * @param latitude2  第二个点的纬度
     * @return 返回距离 单位千米
     */
    public static Long getDistance(double longitude1, double latitude1, double longitude2, double latitude2) {
        // 纬度
        double lat1 = Math.toRadians(latitude1);
        double lat2 = Math.toRadians(latitude2);
        // 经度
        double lng1 = Math.toRadians(longitude1);
        double lng2 = Math.toRadians(longitude2);
        // 纬度之差
        double a = lat1 - lat2;
        // 经度之差
        double b = lng1 - lng2;
        // 计算两点距离的公式
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
                Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(b / 2), 2)));
        // 弧长乘地球半径, 返回单位: 千米
        s = s * EARTH_RADIUS;

// 返回类型: long，单位: 米
        return Math.round(s * 10000) / 10000;
    }


    /**
     * 根据经纬度计算两点间的距离距离
     *
     * @param long1 经度1
     * @param lat1  纬度1
     * @param long2 经度2
     * @param lat2  纬度2
     * @return double 距离，单位是 米
     */
    private static double findDistance(double long1, double lat1, double long2, double lat2) {
        // 地球半径的平均值，
        final double R = 6371393;
        lat1 = lat1 * Math.PI / 180.0;
        lat2 = lat2 * Math.PI / 180.0;
        double a = lat1 - lat2;
        double b = (long1 - long2) * Math.PI / 180.0;
        double sa2 = Math.sin(a / 2.0);
        double sb2 = Math.sin(b / 2.0);
        return 2 * R * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1) * Math.cos(lat2) * sb2 * sb2));
    }


    public static void main(String[] args) {
        String address1 = "四川省成都市金牛区长久一巷51号";
        String address2 = "四川省成都市金牛区中海国际社区中海国际社区绿茵街道";

        String LngLat1 = getLngLat(address1);
        String LngLat2 = getLngLat(address2);
        System.out.println("address1: " + LngLat1);
        System.out.println("address2: " + LngLat2);
        System.out.println("distance: " + getDistance(LngLat1, LngLat2));


        String[] LngLat = LngLat1.split(",");
        double lng1 = Double.parseDouble(LngLat[0]);
        double lat1 = Double.parseDouble(LngLat[1]);
        System.out.println("address1: " + lng1 + "," + lat1);
        String[] LngLat0 = LngLat2.split(",");
        double lng2 = Double.parseDouble(LngLat0[0]);
        double lat2 = Double.parseDouble(LngLat0[1]);
        System.out.println("address2: " + lng2 + "," + lat2);

        System.out.println("distance: " + getDistance(lng1, lat1, lng2, lat2));
        //System.out.println("distance: " + findDistance(lng1, lat1, lng2, lat2));

//        Map<String, Double> map = addressToLngAndLag(address);
//
//        System.out.println("lng:");
//        System.out.println(map.get("lng"));
//        System.out.println("lat:");
//        System.out.println(map.get("lat"));
    }

}
